#ifndef PROTOCOL_H
#define PROTOCOL_H

#include <QDialog>

enum COMMAND
{
    CMD_NONE = 0,
    CMD_PUSH_POWER_DATA = 1,
    CMD_SEND_CHECK_DEVICE,
    CMD_SEND_ACKNAK,
    CMD_RCV_ACKNAK,
    CMD_RCV_CHECK_DEVICE,
    CMD_RCV_POWER_DATA
};

enum RET_ERROR
{
    NO_ERROR = 0,
    ERROR_CONNECT_HOST_TIMEOUT = 0x01,
    ERROR_MAKE_PACKET_FAIL = 0x02,
    ERROR_SEND_FAIL = 0x03,
    ERROR_RECEIVE_TIMEOUT = 0x04,
    ERROR_RECEIVE_INVALID_FRAME = 0x05,
    ERROR_RECEIVE_MISMATCH_FRAME_LENGTH = 0x06,
    ERROR_RECEIVE_INVALID_CHECKSUM = 0x07,
    ERROR_RECEIVE_MISMATCH_DEVICEID = 0x08,
    ERROR_RECEIVE_MISMATCH_FRAMENO = 0x09,
    ERROR_RECEIVE_INVALID_COMMAND = 0x0A,
    ERROR_RECEIVE_INVALID_START = 0x0B

};

enum ERROR_ACKNAK
{
    ACKNAK_NO_ERROR = 0,
    ERROR_COMMAND,
    ERROR_DEVICE_NOTSUPPORT_AREA,
    ERROR_DEVICE_OVER_BYTE_ADDRESS,
    ERROR_DEVICE_OVER_BIT_ADDRESS,
    ERROR_DEVICE_OVER_DATA_LENGTH,
    ERROR_DEVICE_MISMATCH_DATA_LENGTH,
    ERROR_BUSY,
    ERROR_NOTSUPPORT_BYTE_WRITE,
    ERROR_NOTSUPPORT_BIT_WRITE,
    ERROR_NOTSUPPORT_LOG,
    ERROR_LOG_OVER_LOGID,
    ERROR_LOG_READ_INVALID_PARAMETER_LENGTH,
    ERROR_LOG_READ_INVALID_PARAMETER_DATA,
    ERROR_LOG_WRITE_INVALID_DATA_LENGTH,
    ERROR_LOG_WRITE_INVALID_DATA,
    ERROR_MISMATCH_FRAME_NO,
    ERROR_MISMATCH_APP_NO,
    ERROR_NO_LOG_EVENT,
    ERROR_NOTSUPPORT_WRITE_LOG_AREA,
    ERROR_OTHER = 256,
    ERROR_INVALIDE_CHECKSUM
};


// DATA FRAME
// ---------------------------------------------------------------------------------
// |시작 문자|  길  이 |컨트롤|  국 번  | 서브국번|FrameNo|APP일련번호|Data영역|끝문자|체크섬|
// ---------------------------------------------------------------------------------
// | 2Bytes | 2Bytes |1Byte| 2Bytes | 2Bytes | 1Byte | 2Bytes  | 가  변 |1Byte|1Byte|
// ---------------------------------------------------------------------------------
// | 05 43  |        |     |        |        |       |         |       |  03 |     |
// ---------------------------------------------------------------------------------

// ACKNAK FRAME
// ---------------------------------------------------------------------------------
// |시작 문자|  길  이 |컨트롤|  국 번  | 서브국번|FrameNo|APP일련번호|Data영역|끝문자|체크섬|
// ---------------------------------------------------------------------------------
// | 2Bytes | 2Bytes |1Byte| 2Bytes | 2Bytes | 1Byte | 2Bytes  | 2Bytes|1Byte|1Byte|
// ---------------------------------------------------------------------------------
// | 05 43  | 0C 00  |     |        |        |       | 00 00   | 오류코드|  03 |     |
// ---------------------------------------------------------------------------------


// --- Header and Data position in Frame -----
#define HEADER_FRAME_START_POS 0
#define HEADER_FRAME_LENGTH_POS 2
#define HEADER_FRAME_CONTROL_POS 4
#define HEADER_FRAME_DEVICEID_POS 5
#define HEADER_FRAME_SUBDEVICEID_POS 7
#define HEADER_FRAME_FRAMENO_POS 9
#define HEADER_FRAME_APPID_POS 10
#define DATA_FRAME_START_POS 12
// -------------------------------------------

// ------- Header and Tail Markup Data -------
#define HEADER_FRAME_START_ONE 0x05
#define HEADER_FRAME_START_TWO 0x43
#define HEADER_FRAME_END 0x03
// -------------------------------------------

// ------------ Header Control Bit -----------
#define HEADER_FRAME_CONTROL_FIN 0x01
#define HEADER_FRAME_CONTROL_FIR 0x02
#define HEADER_FRAME_CONTROL_PUSH 0x04
#define HEADER_FRAME_CONTROL_ACKNAK 0x80
// -------------------------------------------

// -------------- PUSH LOG Data --------------
#define DATA_FRAME_PUSH_LOG_KIND_ONE 0x01
#define DATA_FRAME_PUSH_LOG_KIND_TWO 0x00
#define DATA_FRAME_PUSH_LOG_ID_0 0x01
// -------------------------------------------

#define DATA_POWERDATA_FRAME_PUSH_LOG_LENGTH 0x04

// -------------- Frame Size -----------------
#define SIZE_ACKNAK_FRAME 16
#define SIZE_CHECK_DEVICEID_FRAME 15

#define TCPIP_TIMEOUT 5000

#define NUM_POWER_CHANNEL 16
typedef struct
{
    quint8 channelNum;
    quint8 dummy;
    quint32 data;
}pushPowerData_t;

typedef struct
{
    quint16 data;
}acknakData_t;

typedef struct {
    COMMAND command;     /**< Command header */
    quint16 deviceID;
    quint8 frameNum;
    quint8 tryCnt;
    union {
        pushPowerData_t pushPowerData;
        acknakData_t    acknakData;
    };
}cmd_t;

class DataPackage
{
public:
    bool buildFrame(cmd_t data, QByteArray* outBuf);
    RET_ERROR parseACKNAK(cmd_t rcvdata, QByteArray block, ERROR_ACKNAK* cause);
    RET_ERROR parseACKNAK_deviceID(cmd_t rcvdata, QByteArray block, quint16* deviceID);
    RET_ERROR parseCheckDEVICEID(QByteArray block);
    ERROR_ACKNAK convert2ACKNAKerror(RET_ERROR error);

private:
    quint16 buildHeader(QByteArray* outBuf, COMMAND cmd, quint16 deviceID, quint8 frameNum);
    unsigned short modbusCrc(unsigned char *data, int length);
};

#endif // PROTOCOL_H
